package org.testfire.util;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.xml.transform.TransformerFactoryConfigurationError;
import org.apache.xerces.dom.DOMOutputImpl;
import org.w3c.dom.*;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSOutput;
import org.w3c.dom.ls.LSSerializer;

public class DOM3XmlWriter
{

    protected File writeTo;

    protected Document doc;

    protected Object[] schemaSource;

    boolean validating = true;

    public DOM3XmlWriter( Document doc, File writeTo )
    {
        this( doc, writeTo, null, false );
    }

    public DOM3XmlWriter( Document doc, File writeTo, Object[] schemaSource, boolean validating )
    {
        this.doc = doc;
        this.writeTo = writeTo;
        this.schemaSource = schemaSource;
        this.validating = validating;
    }

    public DOM3XmlWriter() {}

    ;

    public void writeOut()
    {
        if ( schemaSource != null )
        {
            writeOut( doc, writeTo, schemaSource, validating );
        }
        else
        {
            writeOut( doc, writeTo );
        }
    }

    public void writeOut( File writeTo )
    {
        if ( schemaSource != null && writeTo != null )
        {
            writeOut( doc, writeTo, schemaSource, validating );
        }
        else
        {
            System.err.println( "This Should not have happened in DOM3XMLWriter" );
            return;
        }
    }

    public static void writeOut( Document doc, File writeTo, Object[] schemaSource, boolean validating )
    {

        try
        {

            System.setProperty( DOMImplementationRegistry.PROPERTY,
                "org.apache.xerces.dom.DOMImplementationSourceImpl" );
            DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
            DOMImplementationLS impl = (DOMImplementationLS)registry.getDOMImplementation( "LS" );
            LSSerializer domWriter = impl.createLSSerializer();
            DOMConfiguration config = domWriter.getDomConfig();
            // create Error Handler
            DOMErrorHandler errorHandler = new XMLErrorHandler();

            // set error handler on the Document
            config = doc.getDomConfig();

            // set error handler on the Document
            config = doc.getDomConfig();

            config.setParameter( "error-handler", errorHandler );

            // set validation feature
            if ( validating )
            {
                config.setParameter( "validate", Boolean.TRUE );
            }
            else
            {
                config.setParameter( "validate", Boolean.FALSE );
            }
            // set schema location
            StringBuffer schemas = new StringBuffer();
            for ( int i = 0; i < schemaSource.length; i++ )
            {
                schemas.append( schemaSource[i] );
                schemas.append( " " );
            }

            config.setParameter( "schema-type", "http://www.w3.org/2001/XMLSchema" );
            config.setParameter( "schema-location", schemas.toString() );
            doc.normalize();

            doc.setStrictErrorChecking( true );
            doc.normalizeDocument();
            // serialize document to standard output
            //domWriter.writeNode(System.out, doc);
            LSOutput dOut = new DOMOutputImpl();
            FileOutputStream fos = new FileOutputStream( writeTo );
            dOut.setByteStream( fos );
            domWriter.write( doc, dOut );
            fos.close();
        }
        catch ( FileNotFoundException ex )
        {
            ex.printStackTrace();
        }
        catch ( IOException ex )
        {
            ex.printStackTrace();
        }
        catch ( ClassNotFoundException ex )
        {
            ex.printStackTrace();
        }
        catch ( InstantiationException ex )
        {
            ex.printStackTrace();
        }
        catch ( IllegalAccessException ex )
        {
            ex.printStackTrace();
        }
        catch ( ClassCastException ex )
        {
            ex.printStackTrace();
        }
        catch ( TransformerFactoryConfigurationError ex )
        {
            ex.printStackTrace();
        }
        catch ( IllegalArgumentException ex )
        {
            ex.printStackTrace();
        }
        catch ( DOMException ex )
        {
            ex.printStackTrace();
        }


    }

    public static void writeOut( Node node, File writeTo )
    {
        try
        {
            System.setProperty( DOMImplementationRegistry.PROPERTY,
                "org.apache.xerces.dom.DOMImplementationSourceImpl" );
            DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
            DOMImplementationLS impl = (DOMImplementationLS)registry.getDOMImplementation( "LS" );
            LSSerializer domWriter = impl.createLSSerializer();
            DOMConfiguration config = domWriter.getDomConfig();
            // create Error Handler
            DOMErrorHandler errorHandler = new XMLErrorHandler();

            // set error handler on the Document
            config = node.getOwnerDocument().getDomConfig();

            config.setParameter( "error-handler", errorHandler );

            // set validation feature
            config.setParameter( "validate", Boolean.FALSE );

            System.out.println( "Normalizing document... " );
            node.normalize();

            // serialize document to standard output
            //domWriter.writeNode(System.out, doc);
            LSOutput dOut = new DOMOutputImpl();
            FileOutputStream fos = new FileOutputStream( writeTo );
            dOut.setByteStream( fos );
            domWriter.write( node, dOut );
            fos.close();
        }
        catch ( FileNotFoundException ex )
        {
            ex.printStackTrace();
        }
        catch ( IOException ex )
        {
            ex.printStackTrace();
        }
        catch ( ClassNotFoundException ex )
        {
            ex.printStackTrace();
        }
        catch ( InstantiationException ex )
        {
            ex.printStackTrace();
        }
        catch ( IllegalAccessException ex )
        {
            ex.printStackTrace();
        }
        catch ( ClassCastException ex )
        {
            ex.printStackTrace();
        }
        catch ( TransformerFactoryConfigurationError ex )
        {
            ex.printStackTrace();
        }
        catch ( IllegalArgumentException ex )
        {
            ex.printStackTrace();
        }
        catch ( DOMException ex )
        {
            ex.printStackTrace();
        }
    }


}
